#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
#include <functional>
#include <vector>

using namespace std;

typedef websocketpp::server<websocketpp::config::asio> server;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;

class utility_server {
private:
    //绑定client的哈希表
    vector<websocketpp::connection_hdl> m_hdls;
public:
    utility_server() {
         // 设置log
        m_endpoint.set_error_channels(websocketpp::log::elevel::all);
        m_endpoint.set_access_channels(websocketpp::log::alevel::all ^ websocketpp::log::alevel::frame_payload);
        m_endpoint.set_open_handler(std::bind(&utility_server::on_open, this, ::_1));
        m_endpoint.set_close_handler(std::bind(&utility_server::on_close, this, ::_1));

        // 初始化Asio
        m_endpoint.init_asio();

        // 设置消息回调为echo_handler
        m_endpoint.set_message_handler(std::bind(
            &utility_server::echo_handler, this,
            std::placeholders::_1, std::placeholders::_2
        ));
    }

    void on_open(websocketpp::connection_hdl hdl) {
        m_hdls.push_back(hdl);

        auto connection = m_endpoint.get_con_from_hdl(hdl);
        cout << "current endpoint: " << connection->get_remote_endpoint() << " | clients count: " << m_hdls.size() << endl;
    }

    void on_close(websocketpp::connection_hdl hdl) {
        vector<websocketpp::connection_hdl>::iterator it;
        for (it=m_hdls.begin();it!=m_hdls.end();it++) {
            if ((*it).lock().get() == hdl.lock().get()) {
                m_hdls.erase(it);
                break;
            }
        }
        auto connection = m_endpoint.get_con_from_hdl(hdl);
        cout << "current endpoint: " << connection->get_remote_endpoint() << " | clients count: " << m_hdls.size() << endl;
    }

    void echo_handler(websocketpp::connection_hdl hdl, server::message_ptr msg) {
        vector<websocketpp::connection_hdl>::iterator it;

        std::cout << msg->get_payload() << std::endl;

        for (it=m_hdls.begin();it!=m_hdls.end();it++)
        {
            if ((*it).lock().get() != hdl.lock().get()) {
                m_endpoint.send(*it, msg);
            }
        }
        
    }

    void run() {
        // 监听端口 9002
        m_endpoint.set_reuse_addr(true);
        m_endpoint.listen(9002);

       std::cout << "start_accept" << std::endl;
       
        m_endpoint.start_accept();

        // 开始Asio事件循环
        m_endpoint.run();
    }
private:
    server m_endpoint;
};

int main() {
    utility_server s;
    s.run();
    return 0;
}